<script setup lang="ts">
import { computed, ref, watch } from 'vue';

import { useVbenDrawer } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { cloneDeep, getPopupContainer } from '@vben/utils';
import { Button, message, RangePicker, Tag } from 'ant-design-vue';
import dayjs from 'dayjs';

import { useVbenForm } from '#/adapter/form';
import { trialAdd, trialInfo, trialUpdate } from '#/api/clinical/trial';
import { defaultFormValueGetter, useBeforeCloseDiff } from '#/utils/popup';

import GroupTable from './components/group-table.vue';
import UserSelectionModal from './components/user-selection-modal.vue';
import { drawerSchema } from './data';
import { allProjects } from '#/api/clinical/project';
import { topicList } from '#/api/clinical/topic';
import type { GroupVO } from '#/api/clinical/group/model';
import { allGroups } from '#/api/clinical/group';
import type { User } from '#/api/system/user/model';


const emit = defineEmits<{ reload: [] }>();

const isUpdate = ref(false);
const durationDays = ref<number | null>(null);
const groups = ref<GroupVO[]>([]);
const selectedResearchers = ref<User[]>([]);
const isUserModalVisible = ref(false);

const clinicalTrialId = ref<string | number | undefined>();

const title = computed(() => {
  return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
});

const groupedResearchers = computed(() => {
  return selectedResearchers.value.reduce(
    (acc, user) => {
      const { deptId = 'ungrouped' } = user;
      if (!acc[deptId]) {
        acc[deptId] = [];
      }
      acc[deptId].push(user);
      return acc;
    },
    {} as Record<string, User[]>,
  );
});

watch(selectedResearchers, (newResearchers) => {
  formApi.updateSchema([
    {
      fieldName: 'responsiblePersonId',
      componentProps: {
        options: newResearchers.map(r => ({ label: r.nickName, value: r.userId })),
      },
    },
  ]);
});

function handleChange(newGroups: GroupVO[]) {
  groups.value = newGroups;
}

const [BasicForm, formApi] = useVbenForm({
  commonConfig: {
    formItemClass: 'col-span-1',
    componentProps: {
      class: 'w-full',
    },
  },
  layout: 'vertical',
  schema: drawerSchema(),
  showDefaultActions: false,
  wrapperClass: 'grid-cols-2 gap-x-4',
});

const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff(
  {
    initializedGetter: defaultFormValueGetter(formApi),
    currentGetter: defaultFormValueGetter(formApi),
  },
);

const [BasicDrawer, drawerApi] = useVbenDrawer({
  class: 'w-[800px]',
  onBeforeClose,
  onClosed: handleClosed,
  onConfirm: handleConfirm,
  onOpenChange: async (isOpen) => {
    if (!isOpen) {
      return null;
    }
    drawerApi.drawerLoading(true);
    // 初始化项目下拉框的联动逻辑
    getProjects();
    const { id } = drawerApi.getData() as { id?: number | string };
    clinicalTrialId.value = id;
    isUpdate.value = !!id;

    if (isUpdate.value && id) {
      const record = await trialInfo(id);
      // 关键：先根据回显的项目ID，手动加载对应的课题列表
      if (record.projectId) {
        await getTopicsByProjectId(record.projectId);
      }
      selectedResearchers.value = record.researchers || [];
      record.researcherIds = record.researchers.map(r => r.userId);
      record.cycleDate = [record.startDate, record.endDate]
      // 然后再统一设置表单的值，此时课题下拉框已有选项，可以正确回显
      await formApi.setValues(record);
      durationDays.value = dayjs(record.endDate).diff(dayjs(record.startDate), 'day') + 1
      groups.value = await allGroups({ clinicalTrialId: id });
    } else {
      groups.value = [];
      selectedResearchers.value = [];
    }
    await markInitialized();

    drawerApi.drawerLoading(false);
  },
});

const getProjects = () => {
  formApi.updateSchema([
    {
      fieldName: 'projectId',
      componentProps: (formModel) => ({
        getPopupContainer,
        api: () => allProjects(),
        fieldNames: {
          label: 'name',
          value: 'id',
        },
        onChange: (value: string) => {
          formModel.topicId = undefined;
          formApi.updateSchema([
            {
              componentProps: { options: [] },
              fieldName: 'topicId',
            },
          ]);
          getTopicsByProjectId(value);
        },
      }),
    },
  ]);
};

const getTopicsByProjectId = async (projectId: string | number) => {
  const topics = await topicList({ projectId });
  formApi.updateSchema([
    {
      fieldName: 'topicId',
      componentProps: {
        getPopupContainer,
        options: topics,
        fieldNames: {
          label: 'name',
          value: 'id',
        },
      },
    },
  ]);
};

async function handleRemoveResearcher(removedTag: User) {
  const { responsiblePersonId } = await formApi.getValues();
  if (removedTag.userId === responsiblePersonId) {
    await formApi.setValues({ responsiblePersonId: '' });
  }

  selectedResearchers.value = selectedResearchers.value.filter(
    (tag) => tag.userId !== removedTag.userId,
  );
  await formApi.setValues({
    researcherIds: selectedResearchers.value.map((u) => u.userId),
  });
}

async function handleUserSelectionConfirm(users: User[]) {
  selectedResearchers.value = users;
  const { responsiblePersonId } = await formApi.getValues();
  const researcherIds = users.map(u => u.userId);

  if (responsiblePersonId && !researcherIds.includes(responsiblePersonId)) {
    await formApi.setValues({ responsiblePersonId: undefined });
  }

  await formApi.setValues({
    researcherIds: researcherIds,
  });
}

async function handleConfirm() {
  try {
    drawerApi.lock(true);
    const { valid } = await formApi.validate();
    if (!valid) {
      return;
    }
    const data = cloneDeep(await formApi.getValues());
    data.researcherIds = selectedResearchers.value.map((u) => u.userId);
    data.groupIds = groups.value.map((t) => t.id) || [];
    if (data.groupIds?.length === 0 && data.hasGroups) {
      message.error('分组不能为空');
      return;
    }
    data.startDate = data.cycleDate[0];
    data.endDate = data.cycleDate[1];
    await (isUpdate.value ? trialUpdate(data) : trialAdd(data));
    resetInitialized();
    emit('reload');
    drawerApi.close();
  } catch (error) {
    console.error(error);
  } finally {
    drawerApi.lock(false);
  }
}

async function handleClosed() {
  await formApi.resetForm();
  resetInitialized();
  selectedResearchers.value = [];
  groups.value = [];
  durationDays.value = null;

}
</script>

<template>
  <BasicDrawer :title="title">
    <BasicForm>
      <template #cycleDate="slotProps">
        <div class="flex w-full items-center">
          <RangePicker v-bind="slotProps" class="flex-1" format="YYYY-MM-DD" value-format="YYYY-MM-DD" @change="
            (dates) => {
              if (dates && dates.length === 2) {
                const [start, end] = dates;
                durationDays = dayjs(end).diff(dayjs(start), 'day') + 1;
              } else {
                durationDays = null;
              }
            }
          " />
          <span v-if="durationDays !== null" class="ml-2 whitespace-nowrap text-gray-500">
            (共{{ durationDays }}天)
          </span>
        </div>
      </template>
      <template #researcherIds>
        <div>
          <Button @click="isUserModalVisible = true">选择人员</Button>
          <div class="mt-2">
            <div v-for="(users, groupId) in groupedResearchers" :key="groupId" class="mb-2">
              <div class="font-semibold mb-1">
                {{ users[0]?.deptName || '未分组' }}
              </div>
              <Tag v-for="tag in users" :key="tag.userId" color="blue" closable @close="handleRemoveResearcher(tag)">
                {{ tag.nickName }}
              </Tag>
            </div>
          </div>
        </div>
      </template>
      <template #groupIds>
        <div class="h-[425px] w-full">
          <GroupTable ref="groupTableRef" :clinicalTrialId="clinicalTrialId" :groups="groups" @change="handleChange" />
        </div>
      </template>
    </BasicForm>
    <UserSelectionModal v-model:open="isUserModalVisible" :preselected-users="selectedResearchers"
      @confirm="handleUserSelectionConfirm" />
  </BasicDrawer>
</template>
